#include<iostream>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<assert.h>
using namespace std;


// int main()
// {
//     return 0;
// }



//////////////////////////////////
// //演示十四：
// void handler(int signum)
// {
//     cout << "捕获到一个信号：" << signum << " ,father:"<< getpid() <<endl;
// }

// int main()
// {
//     signal(SIGCHLD ,handler);
//     if( fork() == 0)//子进程
//     {
//         cout << "child pid: " << getpid() << endl;
//         sleep(1);//休眠1s就退出
//         exit(1);
//     }
//     while(true)//父进程
//     {
//         sleep(1);
//     }
//     return 0;
// }



int main()
{
    signal(SIGCHLD, SIG_IGN);

    pid_t cid;
    if ((cid = fork()) == 0)//子进程
    { 
        printf("child : %d\n", getpid());
        sleep(3);
        exit(1);
    }

    while (true)
    {
        printf("father proc：%d,  doing another thing!\n", getpid());
        sleep(1);
    }
    return 0;
}
//////////////////////////////////





//////////////////////////////////
//演示十三：volatile关键字演示
// int flag = 0;//全局变量

// void handler(int sig)
// {
//     (void)sig;
//     cout << "flag: " << flag << " →" ;
//     flag = 1;
//     cout << flag << endl;
// }

// int main()
// {
//     signal(2,handler);
//     cout << "进程运行，捕获信号成功。pid: " << getpid() << endl;
//     while(!flag);
//     cout << "进程正常退出，pid:" << getpid() << " , flag: " << flag << endl;
//     return 0;
// }

//////////////////////////////////




//////////////////////////////////
// //演示十二：sigaction捕获信号
// void Showpending(sigset_t & pending)
// {
//     for(int i = 1; i <= 31; ++i)
//     {
//         if(sigismember(&pending, i)) 
//             cout << 1;
//         else cout << 0;
//     }
//     cout << endl;
// }


// void handler(int signum)
// {
//     cout << "捕获到一个信号：" << signum << endl;
//     sigset_t pending;
//     int count = 30;
//     while(count--)
//     {
//         sigpending(&pending);
//         Showpending(pending);
//         sleep(1);
//     }
// }

// int main()
// {   
//     cout << "getpid: " << getpid() << endl;
//     //1、用户在栈上定义一个内核数据类型的对象
//     struct sigaction act, oact;
//     sigemptyset(&(act.sa_mask));
//     act.sa_flags = 0;
//     act.sa_handler = handler;//函数指针

//     sigaddset(&(act.sa_mask), 1);//把1、3信号也同样屏蔽掉
//     sigaddset(&(act.sa_mask), 3);


//     //2、将用户定义的对象设置进当前调用的进程PCB中
//     sigaction(2, &act, &oact);

//     //3、为方便观察，设置死循环
//     while(true) sleep(1);

//     return 0;
// }

//////////////////////////////////







//////////////////////////////////
// //演示十一：阻塞所有信号，是否能够生成一个不会被异常或者用户杀掉的进程？（基于演示二的延伸）
// void Showpending(sigset_t pending)
// {
//     for(int sig = 1; sig <= 31; ++sig)
//     {
//         if(sigismember(&pending, sig))
//             cout << "1" ;
//         else cout << "0";
//     }
//     cout << endl;
// }

// void Blocksig(int signum)
// {
//     sigset_t obset;
//     sigemptyset(&obset);
//     sigaddset(&obset,signum);

//     int n = sigprocmask(SIG_BLOCK, &obset, nullptr);
//     assert(n == 0);
//     (void)n;
// }

// int main()
// {
//     //依次屏蔽所有信号
//     for(int signum = 1; signum <= 31; ++signum)
//     {
//         Blocksig(signum);
//     }
//     //重复打印当前进程的pending信号集
//     sigset_t pending;
//     cout << "当前进程正在运行，pid：" << getpid() << endl;
//     while(true)
//     {
//         sigpending(&pending);
//         Showpending(pending);
//         sleep(1);
//     }

//     return 0;
// }
//////////////////////////////////





//////////////////////////////////
// //演示十：将2号信号阻塞，获取打印pending信号集，此时发送2号信号，pending信号集中是否对应比特位0→1？
// //对信号进程捕捉：为了方便观察，不让信号执行默认处理动作。
// void handler(int signum)
// {
//     cout << "捕获信号：" << signum << " , pid:" << getpid() << endl;
// }

// //显示信号集
// void Showpending(sigset_t &pending)
// {
//     //int sigismember(const sigset_t *set, int signum);
//     for(int i = 1; i <= 31; ++i)
//     {
//         if(sigismember(&pending, i))
//             cout << "1" ;
//         else
//             cout << "0" ;
//     }
//     cout << endl;
// }

// int main()
// {

//     //1、定义信号集对象
//     sigset_t bset, obset;

//     //2、初始化信号集
//     //int sigemptyset(sigset_t *set);
//     sigemptyset(&bset);
//     sigemptyset(&obset);

//     //3、添加要进行屏蔽(阻塞)的信号
//     //int sigaddset(sigset_t *set, int signum);
//     sigaddset(&bset,2);//此处也可以传递SIGINT

//     //4、设置set到内核中对应的进程内部：上述3步骤只是在用户栈上进行处理，并未设置到OS内部，因此需要借助相关函数达成该功能。
//     //int  sigprocmask(int  how,  const  sigset_t*set, sigset_t *oldset);
//     int ret = sigprocmask(SIG_BLOCK, &bset, &obset);
//     assert(ret == 0);
//     (void)ret;
//     cout << "成功阻塞信号，pid："  << getpid() << endl;

//     //5、重复打印当前进程的pending信号集：用以后续发送2号信号时观察变化
//     sigset_t pending;
//     sigemptyset(&pending);
//     int count = 0;
//     signal(2,handler);//捕获2号信号

//     while(true)
//     {
//         //5.1、获取当前进程的pending信号集
//         //int sigpending(sigset_t *set);
//         sigpending(&pending);
        
//         //5.2、显示pending信号集
//         Showpending(pending);
//         sleep(1);
        
//         //5.3、对2号信号展开恢复：演示0→1→0的过程
//         if(count++ == 10)
//         {
//             cout << "解除对于2号信号的阻塞" << endl;
//             int ret = sigprocmask(SIG_SETMASK, &obset, nullptr);
//             assert(ret == 0 );
//             (void)ret;
//         }
//     }

//     return 0;
// }
//////////////////////////////////




//////////////////////////////////
// //演示九：捕获所有信号，将其处理动作都自定义后，是否能够生成一个不会被异常或杀掉的进程？
// void catchSig(int signum)
// {
//     cout << "当前捕捉到的信号是：" << signum << endl;
// }

// int main()
// {
//     for(int i = 1; i <= 31; ++i )
//     {
//         signal(i, catchSig);//捕获1~31信号，将其处理动作都设置为自定义行为
//     }

//     while(true) sleep(1);//死循环:不让进程结束，方便演示观察现象

//     return 0;
// }
//////////////////////////////////








//////////////////////////////////
// //演示八：硬件异常，除0错误、野指针、越界

// void catchSig(int signum)
// {
//     sleep(1);
//     cout << "捕获到一个信号：" << signum << " ,当前进程为：" << getpid() << endl;
//     exit(11);//测试:进程退出
// }

// int main()
// {
//     signal(SIGSEGV, catchSig);
    
//     int *p = nullptr;
//     *p = 2;

//     while(true) sleep(1);

//     return 0;
// }
//////////////////////////////////






//////////////////////////////////
// //演示六：alarm，验证1s内程序能进行多少次累加
// int main()
// {
//     alarm(1);//设定闹钟：一秒后发送信号14，终止进程

//     int count = 0;
//     while(true)
//     {
//         cout << " count:" << count++ << endl;
//     }

//     return 0;
// }


// //演示七：基于演示六，若想要单纯计算CPU算力（无IO干扰），如何操作？
// uint64_t count = 0;//为了防止int大小不够
// void catchSig(int signum)//typedef void (*sighandler_t)(int);
// {
//     cout<<"进程捕捉到信号：" << signum << " ,pid:" << getpid() << ", count:" << count <<endl;
//     alarm(1);
// }

// int main()
// {
//     signal(SIGALRM, catchSig);//将SIGALRM的处理动作自定义捕捉。

//     alarm(1);//设定闹钟：一秒后发送信号14,SIGALRM

//     while(true) count++; 

//     return 0;
// }
//////////////////////////////////




//////////////////////////////////
// //演示五：系统调用发送信号，abort
// int main( )
// {
//     cout << "当前进程正在运行，pid: " << getpid() << endl;
//     sleep(2);
//     abort();//等同于rasie(6)、kill(getpid(),6)
//     return 0;
// }
//
// 
// 
// 
// 
// //演示四：系统调用发送信号，raise
// int main( )
// {
//     cout << "当前进程正在运行，pid: " << getpid() << endl;
//     sleep(2);
//     raise(8);
//     return 0;
// }
//////////////////////////////////





//////////////////////////////////
// //演示三：kill系统调用接口发生信号

// //int kill(pid_t pid, int sig);
// //演示内容：在命令行中，./mykill 9 pid，终止进程
// static void Usage(string proc)
// {
//     cout << "Usage:\r\n\t" << proc << " signumber processid" << endl;
// }

// int main(int argc, char* argv[])
// {
//     if(argc != 3)//检测命令行指令
//     {
//         Usage(argv[0]);
//         exit(1);
//     }

//     int signumber = atoi(argv[1]);
//     int procid = atoi(argv[2]);
//     kill(procid, signumber);

//     return 0;
// }
//////////////////////////////////






//////////////////////////////////
// //演示二：验证进程等待中的core dump标记位
// int main()
// {
//     pid_t id = fork();
//     if(id == 0)
//     {   //子进程
//         int a = 100;
//         a /= 0;//除数不能为0，此处会报错，信号8：【SIGFPE | Core | Floating point exception】
//         exit(0);
//     }

//     //父进程：进程等待
//     int status = 0;
//     waitpid(id, &status, 0);//阻塞式等待
//     cout <<"父进程:" << getpid() << " ，子进程：" << id << " ,退出信号：" \
//     << (status & 0X7F) << ", is core dump:" << ((status >> 7) & 1) << endl;

//     return 0;
// }
//////////////////////////////////





//////////////////////////////////
// //演示一：进程捕捉：signal
// void catchSig(int signum)//typedef void (*sighandler_t)(int);
// {
//     cout<<"进程捕捉到了一个信号，正在处理该信号：" << signum << " ,pid:" << getpid() <<endl;
// }

// int main()
// {
//     signal(SIGINT,catchSig);//捕捉SIGINT，2号信号，将其处理方式修改为catchSig中的处理方式

//     while(true)//死循环：用于让进行一直运行，方便后续传入信号时，观察现象
//     {
//         cout << "当前进程正在运行，pid: " << getpid() << endl;
//         sleep(1);
//     }

//     return 0;
// }
//////////////////////////////////
